package org.redmagic.service.controller;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.redmagic.service.dao.MagicDao;
import org.redmagic.service.domain.Property;
import org.redmagic.service.utils.ServletUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.common.base.Optional;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

@RequestMapping("/property")
@Controller
public class PropertyController {

	private static final Log LOG = LogFactory.getLog(PropertyController.class);
	
	@Autowired
	private MagicDao magicDao;
	
	@RequestMapping(value = "/**", method = RequestMethod.GET)
	public @ResponseBody ResponseEntity<String> readProperty(HttpServletRequest request) throws UnknownHostException {

		String property = ServletUtils.getProperty(request, "/property/");
		List<String> tags = ServletUtils.getTags(request);

		if (LOG.isInfoEnabled()) {
			LOG.info("[GET] BaseProperty \"" + property + "\", Tags " + tags);
		}
		
		// get the requesting server
		InetAddress address = InetAddress.getByName(request.getRemoteHost());
		String user = address.getHostName();

		LOG.info("User: " + user);
		
		Optional<String> rval = magicDao.getProperty(property, tags, user);
		return returnPropertyStatus(rval);
	}
	
	@RequestMapping(value = "/**", method = RequestMethod.POST)
	public @ResponseBody ResponseEntity<String> createProperty(HttpServletRequest request, @RequestBody JSONObject json) throws UnknownHostException {
		
		// get the requesting server
		InetAddress address = InetAddress.getByName(request.getRemoteHost());
		String user = address.getHostName();
		
		Gson gson = new GsonBuilder().disableHtmlEscaping().create();
		Property property = gson.fromJson(json.toString(), Property.class);
		logCreateOrUpdateProperty(property, "POST");
		
		
		boolean result = magicDao.createProperty(property, user);
		String rval = null;
		if (result) {
			rval = property.getValue();
		}
		return returnPropertyStatus(Optional.fromNullable(rval));
	}
	
	@RequestMapping(value = "/**", method = RequestMethod.PUT)
	public @ResponseBody ResponseEntity<String> updateProperty(HttpServletRequest request, @RequestBody JSONObject json) throws UnknownHostException {

		Gson gson = new GsonBuilder().disableHtmlEscaping().create();
		Property property = gson.fromJson(json.toString(), Property.class);
		logCreateOrUpdateProperty(property, "PUT");
		
		// get the requesting server
		InetAddress address = InetAddress.getByName(request.getRemoteHost());
		String user = address.getHostName();
		
		boolean result = magicDao.updateProperty(property, user);
		String rval = null;
		if (result) {
			rval = property.getValue();
		}
		
		return returnPropertyStatus(Optional.fromNullable(rval));
	}

	private void logCreateOrUpdateProperty(Property createOrUpdateProperty, String method) {
		if (LOG.isInfoEnabled()) {
			LOG.info("[" + method + "] BaseProperty \""
					+ createOrUpdateProperty.getBase()
					+ "\", Tags "
					+ createOrUpdateProperty.getTags()
					+ " and Value \""
					+ createOrUpdateProperty.getValue()
					+ "\"");
		}
	}

	private ResponseEntity<String> returnPropertyStatus(Optional<String> rval) {
		ResponseEntity<String> result;
		if (rval.isPresent()) {

			result = new ResponseEntity<String>(rval.get(), HttpStatus.OK);
		} else {

			result = new ResponseEntity<String>(HttpStatus.NOT_FOUND);
		}

		return result;
	}

	public MagicDao getMagicDao() {
		return magicDao;
	}

	public void setMagicDao(MagicDao magicDao) {
		this.magicDao = magicDao;
	}
}
